/*
* INSANE - Interactive Structural Analysis Environment
*
* Copyright (C) 2003-2005
* Universidade Federal de Minas Gerais
* Escola de Engenharia
* Departamento de Engenharia de Estruturas
* 
* Author's email :    insane@dees.ufmg.br
* Author's website :  http://www.dees.ufmg.br/insane
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
package br.ufmg.dees.insane.model.disc.parametricintegration;

import java.util.ArrayList;
import java.util.ListIterator;

import br.ufmg.dees.insane.model.disc.integrationpoint.IntegrationPoint;
import br.ufmg.dees.insane.model.disc.pointforce.PointForce;
import br.ufmg.dees.insane.util.IMatrix;
import br.ufmg.dees.insane.util.IVector;

/**
*A class representing the parametric integration for volume bulks.<p>
*
*@author Lucas, Marcelo & Pitangueira, Roque
*@version 1.0
*@since Jully 2004
*/

public abstract class Volume extends ParametricIntegration
{
	/** Return the integration order of this Equivalent Nodal Load.
	*@return the integration order of this Equivalent Nodal Load.
	*/
	public abstract int getIntegrationOrder();
	
	/** Return the integration points of this Equivalent Nodal Load.
	*@return the integration points of this Equivalent Nodal Load.
	*/
	protected abstract ArrayList getIntegrationPoints();
	
//********************************************************************************
	
	/** Return the transformation factor to the natural system and cartesian system.
	*@param ip The IntegrationPoint that will be used for the calculation of transformation factor.
	@return double The transformation factor to the natural system and cartesian system.
	*/
	protected double getTransformationFactor(IntegrationPoint ip)
	{
		PointForce pf;
		IMatrix dL;
		IMatrix cN = new IMatrix(this.getPointForcesList().size(),3);
		IMatrix jacob = new IMatrix(3,3);
		cN.setZero();
		jacob.setZero();
		
		ListIterator pfs = this.getPointForcesList().listIterator();
		int i = 0;
		while(pfs.hasNext())
		{
			pf = (PointForce) pfs.next();
			cN.setElement(i,0,((pf.getCoord()).x));
			cN.setElement(i,1,((pf.getCoord()).y));
			cN.setElement(i,2,((pf.getCoord()).z));
			i++;
		}
		dL = (this.getShape()).getDerivedShapeFunction(ip.getCoords());
		jacob.mul(dL,cN);
		
		return (jacob.determinantLU());
	}
	
//********************************************************************************
	
	/** Return the ArrayList containing the parametric integration due to volume loads.
	*@return parIn The ArrayList containing some PointForce according the number of nodes. Each PointForce holds one parametric integration.
	*/
	public ArrayList getIntegralF()
	{
		PointForce pf;
		ArrayList<PointForce> enl = new ArrayList<PointForce>();
		int nNos = this.getPointForcesList().size();
		double L;
		IVector n;
		IMatrix ftip = new IMatrix(nNos, 6);
		ftip.setZero();
		IMatrix ft = new IMatrix(nNos, 6);
		ft.setZero();
		
		ListIterator ips = this.getIntegrationPoints().listIterator();
		while(ips.hasNext())
		{
			IntegrationPoint ip = (IntegrationPoint) ips.next();
			L = this.getTransformationFactor(ip);
			n = (this.getShape()).getShapeFunction(ip.getCoords());
			for(int i = 0; i < 6; i++) // para todos os graus de liberdade
			{
				IVector tNi = new IVector(nNos);//para um grau de liberdade i, armazena os valores de todos os pointforces
				IVector fti = new IVector(n);//instancia fti, fazendo fti = n
				
				ListIterator pfs = this.getPointForcesList().listIterator();
				int k = 0;
				while(pfs.hasNext())
				{
					pf = (PointForce) pfs.next();
					tNi.setElement(k, ((pf.getForces()).getElement(i)));// percorre a lista de pointforces e coloca na posicao k de tNi a forca correspondente ao grau de liberdade i
					k++;
				}
				double nTNi = n.dot(tNi);//produto escalar n*tNi
				fti.scale(((nTNi)*(ip.getWeights())*(L)));// produto: (fti = n) * nTNi * peso do ponto de gauss * L
				ftip.setColumn(i, fti);//cada coluna de ftip representa a contribuicao do grau de liberdade i de um ponto de gauss
			}
			//cada linha de ft representa um vetor com os seis graus de liberdade possiveis
			ft.add(ftip);//adiciona a contribuicao de cada ponto de gauss
		}
imprimeMatriz(ft);

		ListIterator pointfs = this.getPointForcesList().listIterator();
		IVector aux = new IVector(6);
		int b = 0;
		while(pointfs.hasNext())
		{
			pf = (PointForce) pointfs.next();

			PointForce pf1 = new PointForce();
			
			pf1.setCoord(pf.getCoord());
			ft.getRow(b, aux);//atribui a aux os valores da linha b da matrix ft
			for(int a = 0; a < 6; a++)
			{
				pf1.setForce(a, aux.getElement(a));
//				pf.setForce(a, aux.getElement(a));
			}
			aux.zero();
			b++;
			enl.add(pf1);
		}
//		return (this.getPointForcesList());
		return enl;
	}
	
//********************************************************************************
	
	/** Return the ArrayList containing the parametric integration due to area axisymetric loads.
	*@return parIn The ArrayList containing some PointForce according the number of nodes. Each PointForce holds one parametric integration.
	*/
	public ArrayList getIntegralFTimesX()
	{
		return null;
	}
	
//********************************************************************************

}
